package com.oa.core.plupload;

import com.oa.core.utils.FileUtil;
import org.csource.fastdfs.*;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import java.io.*;
import java.util.Iterator;
import java.util.List;

/**
 * Plupload Service模块，同Plupload实体类一样，因为要用到Spring web相关依赖，所以不将其放在Service模块
 */
@Component
public class PluploadService {


    private String conf_filename = this.getClass().getResource("/fdfs_client.conf").getFile();

    public String upload(Plupload plupload,File pluploadDir){
        //在服务器内生成唯一文件名
        String fileName = plupload.getName();
        return upload(plupload, pluploadDir, fileName);
    }

    private void savePluploadFile(InputStream inputStream,File tempFile,boolean flag){
        OutputStream outputStream = null;
        try {
            if(flag==false){
                //从头写入
                outputStream = new BufferedOutputStream(new FileOutputStream(tempFile));
            }
            else{
                //从末端写入
                outputStream = new BufferedOutputStream(new FileOutputStream(tempFile,true));
            }
            byte[] bytes = new byte[1024];
            int len = 0;
            while ((len = (inputStream.read(bytes)))>0){
                outputStream.write(bytes,0,len);
            }
        }
        catch (FileNotFoundException e){
            e.printStackTrace();
        }
        catch (IOException e){
            e.printStackTrace();
        }
        finally {
            try{
                outputStream.close();
                inputStream.close();
            }
            catch (IOException e){
                e.printStackTrace();
            }
        }
    }

    public String upload(File file){
        TrackerServer trackerServer =null;
        StorageServer storageServer = null;
        String fileName = "";
        String fileId = null;
        try {
            ClientGlobal.init(conf_filename);
            TrackerClient tracker = new TrackerClient();
            trackerServer = tracker.getConnection();
            StorageClient client = new StorageClient(trackerServer, storageServer);

            fileName = file.getName();
            String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
            fileId = FileUtil.upload_file5_1(client,file,suffix);


        } catch (Exception e) {
            e.printStackTrace();
        } finally{
            try {
                if(null!=storageServer){
                    storageServer.close();
                }
                if(null!=trackerServer){
                    trackerServer.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return fileId;
    }

    public String upload(MultipartFile file){
        TrackerServer trackerServer =null;
        StorageServer storageServer = null;
        String fileName = "";
        String fileId = null;
        try {
            ClientGlobal.init(conf_filename);
            TrackerClient tracker = new TrackerClient();
            trackerServer = tracker.getConnection();
            StorageClient client = new StorageClient(trackerServer, storageServer);

            fileName = file.getOriginalFilename();
            String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);
            fileId = FileUtil.upload_file5_1(client,file,suffix);


        } catch (Exception e) {
            e.printStackTrace();
        } finally{
            try {
                if(null!=storageServer){
                    storageServer.close();
                }
                if(null!=trackerServer){
                    trackerServer.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return fileId;
    }





    private String upload(Plupload plupload,File pluploadDir,String fileName){

        String filePath = "";

        //用户上传文件被分隔的总块数
        int chunks = plupload.getChunks();
        //当前块，从0开始
        int nowChunk = plupload.getChunk();

        //这里Request请求类型的强制转换可能出错，配置文件中向SpringIOC容器引入multipartResolver对象即可。
        MultipartHttpServletRequest multipartHttpServletRequest  = (MultipartHttpServletRequest)plupload.getRequest();
        //调试发现map中只有一个键值对
        MultiValueMap<String,MultipartFile> map = multipartHttpServletRequest.getMultiFileMap();

        if(map!=null){
            try{
                Iterator<String> iterator = map.keySet().iterator();
                while(iterator.hasNext()){

                    String key = iterator.next();
                    List<MultipartFile> multipartFileList = map.get(key);
                    //循环只进行一次
                    for(MultipartFile multipartFile:multipartFileList){
                        //手动向Plupload对象传入MultipartFile属性值
                        plupload.setMultipartFile(multipartFile);

                        //用户上传资料总块数大于1，要进行合并
                        if(chunks>1){

                            File tempFile = new File(pluploadDir.getPath()+"/"+multipartFile.getName());
                            //第一块直接从头写入，不用从末端写入
                            savePluploadFile(multipartFile.getInputStream(),tempFile,nowChunk==0?false:true);
                            //全部块已经上传完毕，此时targetFile因为有被流写入而存在，要改文件名字
                            if(chunks-nowChunk==1){
                                //新建目标文件，只有被流写入时才会真正存在
                                File targetFile = new File(pluploadDir+"/"+fileName);
                                tempFile.renameTo(targetFile);
                                filePath = upload(targetFile);
                                targetFile.delete();
                            }
                        }
                        else{
                            //只有一块，就直接拷贝文件内容
                            filePath = upload(multipartFile);
                        }
                    }
                }
            }
            catch (IOException e){
                e.printStackTrace();
            }
        }
        return filePath;
    }
}
